/*
XPTracker - Alternative Agile Tracking Tool
Copyright (C) 2006-2009  Stephen Starkey

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
*/
package org.xptracker.web;

import org.apache.commons.beanutils.BeanComparator;
import org.xptracker.domain.*;
import org.xptracker.domain.Queue;
import org.xptracker.persistence.PersistenceManager;

import java.util.*;

public class QueueSource implements StorySource {
  private String queueId;
  private String name;
  private QueueType type;

  public QueueSource(Queue queue) {
    this.queueId = queue.getId();
    this.name = queue.getName();
    this.type = queue.getType();
  }

  @SuppressWarnings({"unchecked"})
  public List<Story> getStories(Domain domain) {
    List<Story> list = getQueue(domain).getStories();
    if (type == QueueType.severity) {
      list = new ArrayList<Story>(list);
      Collections.sort(list, Collections.reverseOrder(new BeanComparator("severity")));
    }
    return list;
  }

  private Queue getQueue(Domain domain) {
    return domain.loadEntity(Queue.class, queueId);
  }

  public String getId() {
    return queueId;
  }

  public String getName() {
    return name;
  }

  public boolean isReorderable() {
    return type == QueueType.priority;
  }

  public boolean isAlive(Domain context) {
    return getQueue(context) != null;
  }

  public void addStory(Domain domain, PersistenceManager.UpdateReceiver receiver, QueueNotifier queueNotifier, Story story) {
    Queue queue = getQueue(domain);
    String reason = "";
    if (story.getQueue() != null) {
      Queue oldQueue = story.getQueue();
      oldQueue.remove(story);
      receiver.update(oldQueue);
      queueNotifier.storyRemoved(oldQueue, story, "Moved to queue " + queue.getName());
      reason = " from " + oldQueue.getName();
    }
    queue.add(story);
    story.setQueue(queue);
    story.setState(State.inQueue);
    story.removeOwner();
    receiver.update(queue);
    receiver.update(story);
    queueNotifier.storyAdded(queue, story, "Added to queue" + reason + ".");
  }

  public void changeOrder(Domain domain, PersistenceManager.UpdateReceiver receiver, SortedMap<Integer,Story> reorderings) {
    if (!isReorderable()) {
      throw new IllegalStateException("Order may not be changed for this queue.");
    }
    Queue queue = getQueue(domain);
    List<Story> stories = new LinkedList<Story>(queue.getStories());
    for(Integer order: reorderings.keySet()) {
      changeOrder(stories, reorderings.get(order), order - 1);
    }
    queue.setStories(new LinkedList<Story>());
    receiver.update(queue);
    queue.setStories(stories);
    receiver.update(queue);
  }

  public String getSourceType() {
    return "Queues";
  }

  public void changeOrder(List<Story> stories, Story story, int newLocation) {
    stories.remove(story);
    if (stories.isEmpty() || newLocation > stories.size()) {
      stories.add(story);
    } else {
      stories.add(newLocation, story);
    }
  }

  public boolean equals(Object o) {
    if (this == o) return true;
    if (o == null || getClass() != o.getClass()) return false;

    final QueueSource that = (QueueSource) o;

    if (queueId != null ? !queueId.equals(that.queueId) : that.queueId != null) return false;

    return true;
  }

  public int hashCode() {
    return (queueId != null ? queueId.hashCode() : 0);
  }
}
